inspector: Introduce so-called "overlays"
authorBenjamin Otte <otte@redhat.com>
Wed, 4 Apr 2018 10:38:09 +0000 (12:38 +0200)
committerBenjamin Otte <otte@redhat.com>
Thu, 5 Apr 2018 12:57:10 +0000 (14:57 +0200)
Overlays are drawings that get rendered on top of the inspected window.

The only overlay in existence so far is the highlight overlay, which is
used to highlight widgets and replaces the "draw" signal handler used
previously.

gtk/inspector/highlightoverlay.c [new file with mode: 0644]
gtk/inspector/highlightoverlay.h [new file with mode: 0644]
gtk/inspector/inspect-button.c
gtk/inspector/inspectoroverlay.c [new file with mode: 0644]
gtk/inspector/inspectoroverlay.h [new file with mode: 0644]
gtk/inspector/meson.build
gtk/inspector/size-groups.c
gtk/inspector/window.c
gtk/inspector/window.h

diff --git a/gtk/inspector/highlightoverlay.c b/gtk/inspector/highlightoverlay.c
new file mode 100644 (file)
index 0000000..869262e
--- /dev/null
@@ -0,0 +1,122 @@
+/*
+ * Copyright © 2018 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#include "config.h"
+
+#include "highlightoverlay.h"
+
+#include "gtkintl.h"
+#include "gtkwidget.h"
+
+struct _GtkHighlightOverlay
+{
+  GtkInspectorOverlay parent_instance;
+
+  GtkWidget *widget;
+  GdkRGBA color;
+};
+
+struct _GtkHighlightOverlayClass
+{
+  GtkInspectorOverlayClass parent_class;
+};
+
+G_DEFINE_TYPE (GtkHighlightOverlay, gtk_highlight_overlay, GTK_TYPE_INSPECTOR_OVERLAY)
+
+static void
+gtk_highlight_overlay_snapshot (GtkInspectorOverlay *overlay,
+                                GtkSnapshot         *snapshot,
+                                GtkWidget           *widget)
+{
+  GtkHighlightOverlay *self = GTK_HIGHLIGHT_OVERLAY (overlay);
+  graphene_rect_t bounds;
+
+  if (!gtk_widget_compute_bounds (self->widget, widget, &bounds))
+    return;
+
+  gtk_snapshot_append_color (snapshot,
+                             &self->color,
+                             &bounds,
+                             "InspectorHighlight");
+}
+
+static void
+gtk_highlight_overlay_queue_draw (GtkInspectorOverlay *overlay)
+{
+  GtkHighlightOverlay *self = GTK_HIGHLIGHT_OVERLAY (overlay);
+
+  gtk_widget_queue_draw (self->widget);
+}
+
+static void
+gtk_highlight_overlay_dispose (GObject *object)
+{
+  GtkHighlightOverlay *self = GTK_HIGHLIGHT_OVERLAY (object);
+
+  g_clear_object (&self->widget);
+
+  G_OBJECT_CLASS (gtk_highlight_overlay_parent_class)->dispose (object);
+}
+
+static void
+gtk_highlight_overlay_class_init (GtkHighlightOverlayClass *klass)
+{
+  GObjectClass *gobject_class = G_OBJECT_CLASS (klass);
+  GtkInspectorOverlayClass *overlay_class = GTK_INSPECTOR_OVERLAY_CLASS (klass);
+
+  overlay_class->snapshot = gtk_highlight_overlay_snapshot;
+  overlay_class->queue_draw = gtk_highlight_overlay_queue_draw;
+
+  gobject_class->dispose = gtk_highlight_overlay_dispose;
+}
+
+static void
+gtk_highlight_overlay_init (GtkHighlightOverlay *self)
+{
+  self->color = (GdkRGBA) { 0.0, 0.0, 1.0, 0.2 };
+}
+
+GtkInspectorOverlay *
+gtk_highlight_overlay_new (GtkWidget *widget)
+{
+  GtkHighlightOverlay *self;
+
+  self = g_object_new (GTK_TYPE_HIGHLIGHT_OVERLAY, NULL);
+
+  self->widget = g_object_ref (widget);
+
+  return GTK_INSPECTOR_OVERLAY (self);
+}
+
+GtkWidget *
+gtk_highlight_overlay_get_widget (GtkHighlightOverlay *self)
+{
+  return self->widget;
+}
+
+void
+gtk_highlight_overlay_set_color (GtkHighlightOverlay *self,
+                                 const GdkRGBA       *color)
+{
+  if (gdk_rgba_equal (&self->color, color))
+    return;
+
+  self->color = *color;
+  gtk_inspector_overlay_queue_draw (GTK_INSPECTOR_OVERLAY (self));
+}
diff --git a/gtk/inspector/highlightoverlay.h b/gtk/inspector/highlightoverlay.h
new file mode 100644 (file)
index 0000000..075e2e6
--- /dev/null
@@ -0,0 +1,38 @@
+/*
+ * Copyright © 2018 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#ifndef __GTK_HIGHLIGHT_OVERLAY_H__
+#define __GTK_HIGHLIGHT_OVERLAY_H__
+
+#include "inspectoroverlay.h"
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_HIGHLIGHT_OVERLAY             (gtk_highlight_overlay_get_type ())
+G_DECLARE_FINAL_TYPE (GtkHighlightOverlay, gtk_highlight_overlay, GTK, HIGHLIGHT_OVERLAY, GtkInspectorOverlay)
+
+GtkInspectorOverlay *   gtk_highlight_overlay_new               (GtkWidget              *widget);
+
+GtkWidget *             gtk_highlight_overlay_get_widget        (GtkHighlightOverlay    *self);
+void                    gtk_highlight_overlay_set_color         (GtkHighlightOverlay    *self,
+                                                                 const GdkRGBA          *color);
+
+G_END_DECLS
+
+#endif /* __GTK_HIGHLIGHT_OVERLAY_H__ */
index 6f1efa1506a0a66740816de1d9fe54498d569e36..ce78c2a8cef862a31ffcb93a1a1b64eaf71715e2 100644 (file)
@@ -25,6 +25,8 @@
 #include <glib/gi18n-lib.h>
 
 #include "window.h"
+
+#include "highlightoverlay.h"
 #include "object-tree.h"
 
 #include "gtkstack.h"
@@ -124,19 +126,13 @@ find_widget_at_pointer (GdkDevice *device)
   return widget;
 }
 
-static gboolean draw_flash (GtkWidget          *widget,
-                            cairo_t            *cr,
-                            GtkInspectorWindow *iw);
-
 static void
 clear_flash (GtkInspectorWindow *iw)
 {
-  if (iw->flash_widget)
+  if (iw->flash_overlay)
     {
-      gtk_widget_queue_draw (iw->flash_widget);
-      g_signal_handlers_disconnect_by_func (iw->flash_widget, draw_flash, iw);
-      g_signal_handlers_disconnect_by_func (iw->flash_widget, clear_flash, iw);
-      iw->flash_widget = NULL;
+      gtk_inspector_window_remove_overlay (iw, iw->flash_overlay);
+      g_clear_object (&iw->flash_overlay);
     }
 }
 
@@ -147,10 +143,8 @@ start_flash (GtkInspectorWindow *iw,
   clear_flash (iw);
 
   iw->flash_count = 1;
-  iw->flash_widget = widget;
-  g_signal_connect_after (widget, "draw", G_CALLBACK (draw_flash), iw);
-  g_signal_connect_swapped (widget, "unmap", G_CALLBACK (clear_flash), iw);
-  gtk_widget_queue_draw (widget);
+  iw->flash_overlay = gtk_highlight_overlay_new (widget);
+  gtk_inspector_window_add_overlay (iw, iw->flash_overlay);
 }
 
 static void
@@ -206,7 +200,8 @@ on_highlight_widget (GtkWidget          *button,
       return;
     }
 
-  if (iw->flash_widget == widget)
+  if (iw->flash_overlay &&
+      gtk_highlight_overlay_get_widget (GTK_HIGHLIGHT_OVERLAY (iw->flash_overlay)) == widget)
     {
       /* Already selected */
       return;
@@ -332,56 +327,20 @@ gtk_inspector_on_inspect (GtkWidget          *button,
   deemphasize_window (GTK_WIDGET (iw));
 }
 
-static gboolean
-draw_flash (GtkWidget          *widget,
-            cairo_t            *cr,
-            GtkInspectorWindow *iw)
-{
-  GtkAllocation alloc;
-
-  if (iw && iw->flash_count % 2 == 0)
-    return FALSE;
-
-  if (GTK_IS_WINDOW (widget))
-    {
-      GtkWidget *child = gtk_bin_get_child (GTK_BIN (widget));
-      /* We don't want to draw the drag highlight around the
-       * CSD window decorations
-       */
-      if (child == NULL)
-        return FALSE;
-
-      gtk_widget_get_allocation (child, &alloc);
-    }
-  else
-    {
-      alloc.x = 0;
-      alloc.y = 0;
-      alloc.width = gtk_widget_get_allocated_width (widget);
-      alloc.height = gtk_widget_get_allocated_height (widget);
-    }
-
-  cairo_set_source_rgba (cr, 0.0, 0.0, 1.0, 0.2);
-  cairo_rectangle (cr,
-                   alloc.x + 0.5, alloc.y + 0.5,
-                   alloc.width - 1, alloc.height - 1);
-  cairo_fill (cr);
-
-  return FALSE;
-}
-
 static gboolean
 on_flash_timeout (GtkInspectorWindow *iw)
 {
-  gtk_widget_queue_draw (iw->flash_widget);
-
   iw->flash_count++;
 
+  gtk_highlight_overlay_set_color (GTK_HIGHLIGHT_OVERLAY (iw->flash_overlay),
+                                   &(GdkRGBA) { 
+                                       0.0, 0.0, 1.0,
+                                       (iw && iw->flash_count % 2 == 0) ? 0.0 : 0.2
+                                   });
+
   if (iw->flash_count == 6)
     {
-      g_signal_handlers_disconnect_by_func (iw->flash_widget, draw_flash, iw);
-      g_signal_handlers_disconnect_by_func (iw->flash_widget, clear_flash, iw);
-      iw->flash_widget = NULL;
+      clear_flash (iw);
       iw->flash_cnx = 0;
 
       return G_SOURCE_REMOVE;
@@ -407,21 +366,6 @@ gtk_inspector_flash_widget (GtkInspectorWindow *iw,
   iw->flash_cnx = g_timeout_add (150, (GSourceFunc) on_flash_timeout, iw);
 }
 
-void
-gtk_inspector_start_highlight (GtkWidget *widget)
-{
-  g_signal_connect_after (widget, "draw", G_CALLBACK (draw_flash), NULL);
-  gtk_widget_queue_draw (widget);
-}
-
-void
-gtk_inspector_stop_highlight (GtkWidget *widget)
-{
-  g_signal_handlers_disconnect_by_func (widget, draw_flash, NULL);
-  g_signal_handlers_disconnect_by_func (widget, clear_flash, NULL);
-  gtk_widget_queue_draw (widget);
-}
-
 void
 gtk_inspector_window_select_widget_under_pointer (GtkInspectorWindow *iw)
 {
diff --git a/gtk/inspector/inspectoroverlay.c b/gtk/inspector/inspectoroverlay.c
new file mode 100644 (file)
index 0000000..a2e1c3d
--- /dev/null
@@ -0,0 +1,71 @@
+/*
+ * Copyright © 2018 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#include "config.h"
+
+#include "inspectoroverlay.h"
+
+#include "gtkintl.h"
+
+typedef struct _GtkInspectorOverlayPrivate GtkInspectorOverlayPrivate;
+
+struct _GtkInspectorOverlayPrivate
+{
+};
+
+G_DEFINE_ABSTRACT_TYPE (GtkInspectorOverlay, gtk_inspector_overlay, G_TYPE_OBJECT)
+
+static void
+gtk_inspector_overlay_default_snapshot (GtkInspectorOverlay *self,
+                                        GtkSnapshot         *snapshot,
+                                        GtkWidget           *widget)
+{
+}
+
+static void
+gtk_inspector_overlay_default_queue_draw (GtkInspectorOverlay *self)
+{
+}
+
+static void
+gtk_inspector_overlay_class_init (GtkInspectorOverlayClass *class)
+{
+  class->snapshot = gtk_inspector_overlay_default_snapshot;
+  class->queue_draw = gtk_inspector_overlay_default_queue_draw;
+}
+
+static void
+gtk_inspector_overlay_init (GtkInspectorOverlay *self)
+{
+}
+
+void
+gtk_inspector_overlay_snapshot (GtkInspectorOverlay *self,
+                                GtkSnapshot         *snapshot,
+                                GtkWidget           *widget)
+{
+  GTK_INSPECTOR_OVERLAY_GET_CLASS (self)->snapshot (self, snapshot, widget);
+}
+
+void
+gtk_inspector_overlay_queue_draw (GtkInspectorOverlay *self)
+{
+  GTK_INSPECTOR_OVERLAY_GET_CLASS (self)->queue_draw (self);
+}
+
diff --git a/gtk/inspector/inspectoroverlay.h b/gtk/inspector/inspectoroverlay.h
new file mode 100644 (file)
index 0000000..867070b
--- /dev/null
@@ -0,0 +1,48 @@
+/*
+ * Copyright © 2018 Benjamin Otte
+ *
+ * This library is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 2.1 of the License, or (at your option) any later version.
+ *
+ * This library is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with this library. If not, see <http://www.gnu.org/licenses/>.
+ *
+ * Authors: Benjamin Otte <otte@gnome.org>
+ */
+
+#ifndef __GTK_INSPECTOR_OVERLAY_H__
+#define __GTK_INSPECTOR_OVERLAY_H__
+
+#include <gtk/gtksnapshot.h>
+
+G_BEGIN_DECLS
+
+#define GTK_TYPE_INSPECTOR_OVERLAY             (gtk_inspector_overlay_get_type ())
+
+G_DECLARE_DERIVABLE_TYPE (GtkInspectorOverlay, gtk_inspector_overlay, GTK, INSPECTOR_OVERLAY, GObject)
+
+struct _GtkInspectorOverlayClass
+{
+  GObjectClass parent_class;
+
+  void                  (* snapshot)                            (GtkInspectorOverlay    *self,
+                                                                 GtkSnapshot            *snapshot,
+                                                                 GtkWidget              *widget);
+  void                  (* queue_draw)                          (GtkInspectorOverlay    *self);
+};
+
+void                    gtk_inspector_overlay_snapshot          (GtkInspectorOverlay    *self,
+                                                                 GtkSnapshot            *snapshot,
+                                                                 GtkWidget              *widget);
+void                    gtk_inspector_overlay_queue_draw        (GtkInspectorOverlay    *self);
+
+G_END_DECLS
+
+#endif /* __GTK_INSPECTOR_OVERLAY_H__ */
index 5dd3a67647cfe6f5078c8acb212a39ebf956833d..7d8fedec78dceef76d741188c1b6ecfffa342d4c 100644 (file)
@@ -11,8 +11,10 @@ inspector_sources = files(
   'gtkstackcombo.c',
   'gtktreemodelcssnode.c',
   'gtktreemodelrendernode.c',
+  'highlightoverlay.c',
   'init.c',
   'inspect-button.c',
+  'inspectoroverlay.c',
   'logs.c',
   'magnifier.c',
   'menu.c',
index fdc4e4d1f220d0cf578dddd0141dae7760d0ba8e..b039eeeb599cc1a9eef95cbf26db2fce48c8ddb4 100644 (file)
@@ -19,6 +19,8 @@
 #include <glib/gi18n-lib.h>
 
 #include "size-groups.h"
+
+#include "highlightoverlay.h"
 #include "window.h"
 
 #include "gtkcomboboxtext.h"
@@ -32,6 +34,7 @@
 
 typedef struct {
   GtkListBoxRow parent;
+  GtkInspectorOverlay *highlight;
   GtkWidget *widget;
 } SizeGroupRow;
 
@@ -139,10 +142,18 @@ size_group_state_flags_changed (GtkWidget     *widget,
   state = gtk_widget_get_state_flags (widget);
   if ((state & GTK_STATE_FLAG_PRELIGHT) != (old_state & GTK_STATE_FLAG_PRELIGHT))
     {
+      GtkInspectorWindow *iw = GTK_INSPECTOR_WINDOW (gtk_widget_get_toplevel (widget));
+
       if (state & GTK_STATE_FLAG_PRELIGHT)
-        gtk_inspector_start_highlight (row->widget);
+        {
+          row->highlight = gtk_highlight_overlay_new (row->widget);
+          gtk_inspector_window_add_overlay (iw, row->highlight);
+        }
       else
-        gtk_inspector_stop_highlight (row->widget);
+        {
+          gtk_inspector_window_remove_overlay (iw, row->highlight);
+          g_clear_object (&row->highlight);
+        }
     }
 }
 
index 428de723c6c07479a7f12fff38e13247728fa470..13b0ff7b6cd80a84c2b5d88bb8081b3c3768ef75 100644 (file)
@@ -355,6 +355,30 @@ gtk_inspector_window_new (void)
                                    NULL));
 }
 
+void
+gtk_inspector_window_add_overlay (GtkInspectorWindow  *iw,
+                                  GtkInspectorOverlay *overlay)
+{
+  iw->overlays = g_list_prepend (iw->overlays, g_object_ref (overlay));
+
+  gtk_inspector_overlay_queue_draw (overlay);
+}
+
+void
+gtk_inspector_window_remove_overlay (GtkInspectorWindow  *iw,
+                                     GtkInspectorOverlay *overlay)
+{
+  GList *item;
+
+  item = g_list_find (iw->overlays, overlay);
+  if (item == NULL)
+    return;
+
+  gtk_inspector_overlay_queue_draw (overlay);
+
+  iw->overlays = g_list_delete_link (iw->overlays, item);
+}
+
 void
 gtk_inspector_window_rescan (GtkWidget *widget)
 {
@@ -393,6 +417,23 @@ gtk_inspector_prepare_render (GtkWidget            *widget,
                                         region,
                                         node);
 
+  if (iw->overlays)
+    {
+      GtkSnapshot *snapshot;
+      GList *l;
+
+      snapshot = gtk_snapshot_new (FALSE, "Inspector Overlay");
+      gtk_snapshot_append_node (snapshot, node);
+
+      for (l = iw->overlays; l; l = l->next)
+        {
+          gtk_inspector_overlay_snapshot (l->data, snapshot, widget);
+        }
+
+      gsk_render_node_unref (node);
+      node = gtk_snapshot_free_to_node (snapshot);
+    }
+
   return node;
 }
 
index a9597b22bc58b4d58c3b70d9d066cc7669dbde82..cc72aeecbf6faf14293df2a9cafd28fe79b00ef1 100644 (file)
@@ -26,6 +26,8 @@
 
 #include <gtk/gtkwindow.h>
 
+#include "inspectoroverlay.h"
+
 #define GTK_TYPE_INSPECTOR_WINDOW            (gtk_inspector_window_get_type())
 #define GTK_INSPECTOR_WINDOW(obj)            (G_TYPE_CHECK_INSTANCE_CAST((obj), GTK_TYPE_INSPECTOR_WINDOW, GtkInspectorWindow))
 #define GTK_INSPECTOR_WINDOW_CLASS(klass)    (G_TYPE_CHECK_CLASS_CAST((klass), GTK_TYPE_INSPECTOR_WINDOW, GtkInspectorWindowClass))
@@ -72,15 +74,17 @@ typedef struct
 
   GtkWidget *invisible;
   GtkWidget *selected_widget;
-  GtkWidget *flash_widget;
 
   GList *extra_pages;
 
   gboolean grabbed;
 
+  GtkInspectorOverlay *flash_overlay;
   gint flash_count;
   gint flash_cnx;
 
+  GList *overlays;
+
 } GtkInspectorWindow;
 
 typedef struct
@@ -96,12 +100,15 @@ GtkWidget *gtk_inspector_window_new         (void);
 
 void       gtk_inspector_flash_widget       (GtkInspectorWindow *iw,
                                              GtkWidget          *widget);
-void       gtk_inspector_start_highlight    (GtkWidget          *widget);
-void       gtk_inspector_stop_highlight     (GtkWidget          *widget);
 
 void       gtk_inspector_on_inspect         (GtkWidget          *widget,
                                              GtkInspectorWindow *iw);
 
+void                    gtk_inspector_window_add_overlay                        (GtkInspectorWindow     *iw,
+                                                                                 GtkInspectorOverlay    *overlay);
+void                    gtk_inspector_window_remove_overlay                     (GtkInspectorWindow     *iw,
+                                                                                 GtkInspectorOverlay    *overlay);
+
 void                    gtk_inspector_window_select_widget_under_pointer        (GtkInspectorWindow     *iw);
 
 void                    gtk_inspector_window_rescan                             (GtkWidget              *iw);